/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.biotecan.easywgs;

import com.biotecan.easywgs.domain.Lane;
import com.biotecan.easywgs.domain.Library;
import com.biotecan.easywgs.domain.Sample;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.security.CodeSource;
import java.util.Date;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;

/**
 *
 * @author SuFeng
 */
public class CommandLineProgram {

    private static final String USAGE = "java -jar EasyWGS.jar [-h] <-n sampleName> <-i config>";

    protected Options opts = new Options();

    protected CommandLineParser parser = new DefaultParser();

    protected CommandLine commandLine;

    /**
     * 配置文件信息
     */
    protected File configFile;

    /**
     * 样本名称
     */
    protected String sampleName;
    
    /**
     * 输入fastq文件扩展名，默认为fq.gz
     */
    protected String extension = "fq.gz";

    /**
     * 默认为全基因组分析流程
     */
    protected AnalysisType type = AnalysisType.wgs;

    /**
     * 程序运行工作目录，默认为当前所在目录
     */
    protected String workingDirectory;

    /**
     * 捕获区域文件
     */
    protected String targetRegion;

    public CommandLineProgram() {

    }

    public int instanceAndWithExit(String args[]) {
        try {
            opts.addOption("h", false, "show usage");

            Option name = new Option("t", true, "analysis type.default is wgs . values can be { wgs,wes, clearseq}");
            name.setRequired(true);
            opts.addOption(name);

            Option workDir = new Option("d", true, "sample file direcotry ,default is current working direcotry");
            opts.addOption(workDir);

            Option input = new Option("i", true, "input config file,required");
            input.setRequired(true);
            opts.addOption(input);

            //是否有提供捕获区域bed文件
            Option target = new Option("r", true, "target region file");
            target.setRequired(false);
            opts.addOption(target);
            
            Option fileExtension= new Option("e", true, "file extension. default value is fq.gz");
            target.setRequired(false);
            opts.addOption(fileExtension);
            
            
            //解析命令行输入参数信息
            commandLine = parser.parse(opts, args);

            //如果没有输入任何参数或者输入了-h ,则打印使用指南
            if (commandLine.getOptions().length == 0 || commandLine.hasOption("-h")) {
                printHelp();
                return ProgramConstants.ERROR;
            } else {
                
                type = AnalysisType.valueOf(commandLine.getOptionValue("t"));

                workingDirectory = commandLine.getOptionValue("d", "./");

                String config = commandLine.getOptionValue("i");

                configFile = new File(config);
                if (!Files.exists(configFile.toPath())) {
                    System.err.println("config file is not exists.");
                    printHelp();
                    return ProgramConstants.ERROR;
                }

               if (commandLine.hasOption("r")) {
                    targetRegion = commandLine.getOptionValue("r");
                }
               
               if(commandLine.hasOption("-e")){
                   extension = commandLine.getOptionValue("e");
               }

                return doWork();

            }
        } catch (ParseException ex) {
            //Logger.getLogger(CommandLineProgram.class.getName()).log(Level.SEVERE, null, ex);
            printHelp();
            return ProgramConstants.ERROR;
        }
    }

    public static void main(String args[]) {
        //args = new String[]{"-i", "D:/test.txt", "-t", "wes", "-d", "D:/","-r","aaaa"};
        CommandLineProgram commandLineProgram = new CommandLineProgram();
        commandLineProgram.instanceAndWithExit(args);
    }

    private void printHelp() {
        HelpFormatter hf = new HelpFormatter();
        hf.printHelp(USAGE, "", opts, "");
    }

    /**
     * the main method
     */
    private int doWork() {

        try {
            Sample sample = createSample();

            String path = getJarContainingFolder(CommandLineProgram.class).replaceAll("\\\\", "/");
            //System.out.println("Application install path is " + path);
            //初始化参数
            Properties properties = new Properties();
            //设置velocity资源加载方式为file
            //properties.setProperty("resource.loader", "file");
            //设置velocity资源加载方式为file时的处理类
            properties.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
            properties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, path + "/resources/template");
            properties.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
            properties.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
            properties.setProperty(Velocity.ENCODING_DEFAULT, "UTF-8");
            VelocityEngine ve = new VelocityEngine();
            ve.init(properties);

            //for test
            //org.apache.velocity.Template snpAndIndelTemplate = ve.getTemplate("src/main/resources/template/easy" + type.name() + ".vsl", "utf-8");
            //org.apache.velocity.Template freecTemplate = ve.getTemplate("src/main/resources/template/freec.vsl", "utf-8");
            org.apache.velocity.Template snpAndIndelTemplate = ve.getTemplate("easy_" + type.name() + ".vsl", "utf-8");

            //org.apache.velocity.Template freecTemplate = ve.getTemplate("freec.vsl", "utf-8");
            // 取得velocity的上下文context
            VelocityContext context = new VelocityContext();

            context.put("evaluate", true);
            context.put("batch", true);
            context.put("sample", sample);
            context.put("librarys", sample.getLibrarys());
            context.put("workingDirectory", workingDirectory);
            context.put("targetRegion", targetRegion);
            context.put("extension", extension);
            

            
            //; Writer freec = new OutputStreamWriter(new FileOutputStream(workingDirectory + "/" + sample.getSampleName() + ".freec.qsub"), "utf-8")
            try (Writer snpAndIndel = new OutputStreamWriter(new FileOutputStream(workingDirectory + "/" + sample.getSampleName() + ".qsub"), "utf-8")) {
                snpAndIndelTemplate.merge(context, snpAndIndel);
                //freecTemplate.merge(context, freec);
                snpAndIndel.flush();
                // freec.flush();
            }

        } catch (IOException ex) {
            Logger.getLogger(CommandLineProgram.class.getName()).log(Level.SEVERE, null, ex);
            return ProgramConstants.ERROR;
        } catch (Exception ex) {
            Logger.getLogger(CommandLineProgram.class.getName()).log(Level.SEVERE, null, ex);
            return ProgramConstants.ERROR;
        }
        return ProgramConstants.OK;
    }

    /**
     * create a sample object with config file
     *
     * @return Sample
     * @throws IOException
     */
    private Sample createSample() throws IOException {
        BufferedReader reader = Files.newBufferedReader(configFile.toPath(), Charset.defaultCharset());
        String line;
        String[] array;
        String[] lanes;
        //Sample sample = new Sample(sampleName);
        Sample sample = new Sample();
        sample.setCreateDate(new Date());
        //per line per library 
        while ((line = reader.readLine()) != null) {
            array = line.split("(\t|:|,)", -1);
            sampleName = array[0];
            sample.setSampleName(sampleName);
            Library library = new Library(array[1]);
            lanes = array[2].split("\\|", -1);
            for (String lane : lanes) {
                library.addLane(new Lane(lane, new File(workingDirectory + "/" + sampleName + "_" + library.getName() + "_" + lane + "_1.fq.gz"), new File(workingDirectory + "/" + sampleName + "_" + library.getName() + "_" + lane + "_2.fq.gz")));
            }
            sample.addLibrary(library);
        }

        return sample;
    }

    public static String getJarContainingFolder(Class aclass) throws Exception {
        CodeSource codeSource = aclass.getProtectionDomain().getCodeSource();

        File jarFile;

        if (codeSource.getLocation() != null) {
            jarFile = new File(codeSource.getLocation().toURI());
        } else {
            String path = aclass.getResource(aclass.getSimpleName() + ".class").getPath();
            String jarFilePath = path.substring(path.indexOf(":") + 1, path.indexOf("!"));
            jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8");
            jarFile = new File(jarFilePath);
        }
        return jarFile.getParentFile().getAbsolutePath();
    }

}
